package com.example.flower_shop.controller;

import com.example.flower_shop.common.ApiResponse;
import com.example.flower_shop.dto.PageRequest;
import com.example.flower_shop.dto.product.CreateProductRequest;
import com.example.flower_shop.dto.product.ProductVO;
import com.example.flower_shop.dto.product.UpdateProductRequest;
import com.example.flower_shop.entity.Product;
import com.example.flower_shop.service.ProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.Min;
import java.util.List;
import java.util.stream.Collectors;

@Validated
@RestController
@RequestMapping("/api/products")
@RequiredArgsConstructor
public class ProductController {

    private final ProductService productService;

    @GetMapping
    public ApiResponse<Page<ProductVO>> listProducts(@Valid PageRequest pageRequest) {
        Page<Product> products = productService.findAll(pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/category/{categoryId}")
    public ApiResponse<Page<ProductVO>> listProductsByCategory(
            @PathVariable Long categoryId,
            @Valid PageRequest pageRequest) {
        Page<Product> products = productService.findByCategoryId(categoryId, pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/available")
    public ApiResponse<Page<ProductVO>> listAvailableProducts(@Valid PageRequest pageRequest) {
        Page<Product> products = productService.findAvailableProducts(pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/available/category/{categoryId}")
    public ApiResponse<Page<ProductVO>> listAvailableProductsByCategory(
            @PathVariable Long categoryId,
            @Valid PageRequest pageRequest) {
        Page<Product> products = productService.findAvailableProductsByCategory(categoryId,
                pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/search")
    public ApiResponse<List<ProductVO>> searchProducts(
            @RequestParam String name,
            @RequestParam(required = false, defaultValue = "1") Integer status) {
        List<Product> products = productService.findByNameAndStatus(name, status);
        List<ProductVO> productVOs = products.stream()
                .map(ProductVO::new)
                .collect(Collectors.toList());
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/{id}")
    public ApiResponse<ProductVO> getProduct(@PathVariable Long id) {
        Product product = productService.findById(id)
                .orElseThrow(() -> new RuntimeException("商品不存在"));
        return ApiResponse.success(new ProductVO(product));
    }

    @PostMapping
    public ApiResponse<ProductVO> createProduct(@Valid @RequestBody CreateProductRequest request) {
        Product product = productService.createProduct(
                request.getCategoryId(),
                request.getName(),
                request.getDescription(),
                request.getPrice(),
                request.getStock(),
                request.getImageUrl());
        return ApiResponse.success(new ProductVO(product));
    }

    @PutMapping("/{id}")
    public ApiResponse<ProductVO> updateProduct(
            @PathVariable Long id,
            @Valid @RequestBody UpdateProductRequest request) {
        Product product = productService.updateProduct(
                id,
                request.getCategoryId(),
                request.getName(),
                request.getDescription(),
                request.getPrice(),
                request.getStock(),
                request.getImageUrl());
        return ApiResponse.success(new ProductVO(product));
    }

    @PutMapping("/{id}/stock")
    public ApiResponse<ProductVO> updateStock(
            @PathVariable Long id,
            @RequestParam @Valid @Min(0) Integer stock) {
        Product product = productService.updateStock(id, stock);
        return ApiResponse.success(new ProductVO(product));
    }

    @PutMapping("/{id}/status")
    public ApiResponse<ProductVO> updateStatus(
            @PathVariable Long id,
            @RequestParam Integer status) {
        Product product = productService.updateStatus(id, status);
        return ApiResponse.success(new ProductVO(product));
    }

    @DeleteMapping("/{id}")
    public ApiResponse<Void> deleteProduct(@PathVariable Long id) {
        productService.deleteById(id);
        return ApiResponse.success(null);
    }

    @GetMapping("/carousel")
    public ApiResponse<List<ProductVO>> getCarouselProducts() {
        List<Product> products = productService.findCarouselProducts();
        List<ProductVO> productVOs = products.stream()
                .map(ProductVO::new)
                .collect(Collectors.toList());
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/recommend")
    public ApiResponse<Page<ProductVO>> getRecommendProducts(@Valid PageRequest pageRequest) {
        Page<Product> products = productService.findRecommendedProducts(pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @GetMapping("/hot")
    public ApiResponse<Page<ProductVO>> getHotProducts(@Valid PageRequest pageRequest) {
        Page<Product> products = productService.findHotProducts(pageRequest.toPageRequest());
        Page<ProductVO> productVOs = products.map(ProductVO::new);
        return ApiResponse.success(productVOs);
    }

    @PutMapping("/{id}/display")
    public ApiResponse<ProductVO> updateDisplayProperties(
            @PathVariable Long id,
            @RequestParam(required = false) Boolean isCarousel,
            @RequestParam(required = false) Boolean isRecommended,
            @RequestParam(required = false) Boolean isHot,
            @RequestParam(required = false) Integer carouselSort,
            @RequestParam(required = false) Integer recommendSort) {
        Product product = productService.updateDisplayProperties(
                id, isCarousel, isRecommended, isHot, carouselSort, recommendSort);
        return ApiResponse.success(new ProductVO(product));
    }
}